package learn;

import com.sun.xml.internal.ws.api.client.ThrowableInPacketCompletionFeature;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;

/**
 * @Description:
 * @Version 1.0, 2021/12/8
 * @Author Tim
 */
public class ConcurrentApi {
    /**
     *
     */
    public static void thread(){
        Runnable runnable;
        Thread thread = new Thread();
        // 中断时通知线程，由线程决定如何处理中断。
        // 阻塞中的线程，只抛异常，中断不置位；如需判定中断，再次中断线程 Thread.currentThread().interrupt();
        // 运行中线程，中断置true
        thread.interrupt();
        Thread.interrupted();// 调用后中断置false
        thread.isInterrupted();// 调用后不重置中断标志

        Executor executor;
        Executors executors;// 工具类
        ExecutorService executorService;
        Callable callable;
        Future future;

    }

    /**
     * synchronized；基于jvm
     * LockSupport；基于硬件指令
     *  Lock；synchronized
     *  Condition；监视器操作
     */
    public static void lock(){
        // 锁
        Lock lock;
        ReentrantLock reentrantLock;
        LockSupport lockSupport;

        // 读写锁
        ReadWriteLock readWriteLock;
        ReentrantReadWriteLock reentrantReadWriteLock;

        //
        StampedLock stampedLock;

        // 锁实现框架
        AbstractQueuedSynchronizer aqs;
    }

    /**
     * 线程间通信
     */
    public static void coordinate() throws Exception {
        /*
         * synchronized监视器；监视器包含阻塞队列、等待队列
         *  1，obj未被占用，获取obj监视器
         *  2，obj已被占用，阻塞线程，不释放已持有监视器；加入阻塞队列，等待JVM唤醒
         *  3，Object#wait；阻塞线程，释放obj监视器(必须持有obj监视器)，加入等待队列，等待notify将其移入阻塞队列
         *  4，Object#notify；不释放监视器、不阻塞线程，将obj监视器等待队列中元素移入阻塞队列
         *  5，释放监视器：同步代码结束、Object#wait
         */
        Object obj = null;
        synchronized (obj){
            // 可能虚假唤醒，应在循环中使用；通过额外条件判定是否满足唤醒条件
            obj.wait(0);
            obj.notify();
            obj.notifyAll();
        }


        /*
         * Thread api
         */
        Thread thread=null;
        thread.join(0);// 为同步方法，调用thread.wait暂停当前线程，thread线程终止时自动调用notifyAll
        Thread.sleep(1);// 阻塞线程，不丢失监视器
        Thread.yield();// 让步，加入OS线程调度列表；不丢失监视器

        /*
         * Lock，synchronized。lock获取监视器，unlock释放监视器
         * Condition，监视器。await释放监视器，signal唤醒等待的线程
         * AbstractQueuedSynchronizer中，Node自链表作阻塞队列
         */
        Lock lock=null;
        lock.lock();
        lock.unlock();

        // AbstractQueuedSynchronizer.Node自链表，作等待队列；持有head、tail
        Condition condition=lock.newCondition();
        condition.await();
        condition.signal();// 从等待队列，移入阻塞队列
        condition.signalAll();

    }


    /**
     * 并发工具集
     */
    public static void concurrentUtil() throws Exception {
        // 集合；阻塞队列
        SynchronousQueue synchronousQueue;// 同步队列
        LinkedTransferQueue linkedTransferQueue;// 无界阻塞队列
        LinkedBlockingQueue linkedBlockingQueue;// 一个正常的基于链表结构的阻塞队列， 无界队列.
        LinkedBlockingDeque linkedBlockingDeque;// 双向链表组成的队列

        // 线程协调
        Semaphore semaphore=new Semaphore(3);// 信号量。令牌桶，限流
        semaphore.acquire();// 获取许可，无时阻塞
        semaphore.release();// 释放许可
        CountDownLatch countDownLatch=new CountDownLatch(5);// 倒计数
        countDownLatch.await();// 阻塞线程，直到倒计数为0
        countDownLatch.countDown();// 倒计数-1；计数达到零，则释放所有等待的线程。
        CyclicBarrier cyclicBarrier=new CyclicBarrier(5);// 循环栅栏；可重置的CountDownLatch
        cyclicBarrier.await();// 计数-1；阻塞线程，直到倒计数为0
        cyclicBarrier.reset();// 重置计数
    }

    /**
     * https://www.cnblogs.com/waterystone/p/4920797.html
     *
     */
    public static void aqs(){
        AbstractQueuedSynchronizer aqs=null;
        /*
         * 阻塞队列节点；包含线程、等待状态等
         *
         * 等待状态：
         *  CANCELLED；1，已取消调度。超时、中断
         *  SIGNAL；-1，后继节点等待当前节点唤醒。后继节点入队时，会将prev改为SIGNAL
         *  CONDITION；-2，当前节点等待在Condition上。
         *      其他节点调用Condition.signal()后，从等待队列移入同步队列，等待获取同步锁
         *  PROPAGATE；-3，共享模式下，prev会唤醒后继节点、后继节点的后继。
         *  0；新节点入队时默认状态
         *  负值为有效等待状态；正值为节点已被取消。
         */
        AbstractQueuedSynchronizer.Node node;

        int times = 1;// 重入次数
        aqs.acquire(times);// 获取锁；失败时加入阻塞队列，找到前序节点，等待获取锁
        {
            // 1，尝试获取锁
            aqs.tryAcquire(times);
            // 2，获取锁失败，构建Node，加入到等待队列队尾
            // CAS自旋(Unsafe实现)、volatile可见性
            AbstractQueuedSynchronizer.Node node1 = aqs.addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE);
            // 3，自旋等待
            aqs.acquireQueued(node1, times);
            {
                // 3.1，为队列第二节点，尝试获取锁。可能是head未唤醒、interrupt等
                aqs.tryAcquire(times);
                // 3.2，选择并设置前序节点状态，阻塞线程。
                // 阻塞后，两种方式唤醒：unpark、interrupt
                aqs.shouldParkAfterFailedAcquire(node1.predecessor(), node1);
                aqs.parkAndCheckInterrupt();// LockSupport.lock

            }
            // 4，如在等待获取锁时被中断，不响应；获取锁后中断线程。防止无法通知？
            aqs.selfInterrupt();
        }

        aqs.release(times);
        {
            // 1，释放锁
            aqs.tryRelease(times);
            // 2，唤醒后继节点。
            // 后继节点waitStatus<0，若不满足，继续往后查找；查找到null，则从后往前查找
            aqs.unparkSuccessor(node);// head通知唤醒后继节点
            LockSupport.unpark(null);

        }

        /*
         * 基于Unsafe
         */
        LockSupport.park();
        LockSupport.unpark(Thread.currentThread());

    }

    /**
     *
     */
    public static void threadLocal(){
        /*
         * 多线程中，关联静态变量
         *  ThreadLocal，Thread的threadLocals属性，不可继承
         *  InheritableThreadLocal对应inheritableThreadLocals属性，可继承
         *
         * 线性探索，处理hash冲突
         */
        ThreadLocal threadLocal=null;
        threadLocal.set(null);// 设置。getter、setter都可能触发无效key清除
        threadLocal.get();// 获取
        threadLocal.remove();// 移除

        // 子类；提供初始值
        threadLocal = new ThreadLocal(){
            // 供重写的初始化方法
            protected Object initialValue() { return null;}
        };
        ThreadLocal.SuppliedThreadLocal child =
                (ThreadLocal.SuppliedThreadLocal)ThreadLocal.withInitial((Supplier)null);
        // 可继承的，Thread的inheritableThreadLocals属性；子线程可继承父线程的ThreadLocal数据
        InheritableThreadLocal inheritableThreadLocal;

        // ThreadLocal存值；ThreadLocal.set中初始化
        // Entry数组存储数据，key为ThreadLocal的弱引用；哈希值计算槽位数据，冲突时rehash
        ThreadLocal.ThreadLocalMap threadLocalMap=null;
        Thread thread=Thread.currentThread();

    }

    /**
     * https://www.cnblogs.com/cjsblog/p/9078341.html
     */
    public static void forkJoinPool(){
        /*
         * 每个线程有单独的任务队列；
         */
        ForkJoinPool forkJoinPool=null;
        forkJoinPool.execute((ForkJoinTask)null);
        forkJoinPool.invoke((ForkJoinTask)null);
        forkJoinPool.submit((ForkJoinTask)null);
        // ForkJoinWorkerThread线程中执行fork，提交到本线程执行；否则重新分配线程
        ForkJoinWorkerThread forkJoinWorkerThread;
        ForkJoinPool.WorkQueue workQueue;// 任务队列

        ForkJoinTask forkJoinTask=null;// 实现Future
        forkJoinTask.fork();// 任务提交到线程池，forkJoinPool 或者 ForkJoinPool.common
        forkJoinTask.join();// 线程池中获取线程，同步执行，获取结果。已fork时弹出执行
        {
            RecursiveAction action;// 无返回任务
            RecursiveTask task;// 有返回任务
            CountedCompleter countedCompleter;// 无返回带回调的任务
        }

    }

    class Fibonacci extends RecursiveTask<Integer> {
        final int n;
        Fibonacci(int n) { this.n = n; }
        @Override
        public Integer compute() {
            if (n <= 1)
                return n;
            Fibonacci f1 = new Fibonacci(n - 1);
            f1.fork();// 任务提交到线程池
            Fibonacci f2 = new Fibonacci(n - 2);
            return f2.compute() + f1.join();// 同步执行，获取结果
        }
    }

    /**
     * https://www.cnblogs.com/ITtangtang/p/3948786.html
     * 并发扩容
     * 高低位迁移
     * 分段锁
     * 链表、红黑树
     *
     */
    public static void concurrentHashMap(){
        HashMap hashMap=null;// 线程不安全；并发插入同hashCode key，多线程各自扩容
        {
            hashMap.put(null, null);
            hashMap.resize();// 扩容
        }
        Hashtable hashtable;// 同步方法

        //
        ConcurrentHashMap concurrentHashMap=null;
        {
            concurrentHashMap.put(null, null);
            concurrentHashMap.tryPresize();// 扩容，UNSAFE加锁
        }
        // 数据存于Node[]；table、nextTable(用于扩容)
        ConcurrentHashMap.Node node;


    }

    /**
     *
     */
    public static void java8Async(){
        // java 1
        Runnable runnable;
        Thread thread;// 实现Runnable

        // java 5
        Callable callable;
        Future future;
        Executor executor;// 线程池
        // 执行Callable，返回Future
        ExecutorService executorService=null;
        {
            AbstractExecutorService abstractExecutorService=null;
            // 实现了Runnable、Future
            RunnableFuture ftask = abstractExecutorService.newTaskFor(null);
            abstractExecutorService.execute(ftask);

            // 封装为FutureTask对象；执行run方法，设置result；多线程间共享同一实例，实现数据传递
            // 同步非阻塞方式；会在getter处阻塞，非回调
            // LockSupport；阻塞、唤醒线程
            FutureTask futureTask;
            LockSupport.park();
            LockSupport.unpark(null);

        }
        // 线程池状态：
        //  RUNNING：接受新任务并处理排队任务
        //  SHUTDOWN：不接受新任务，但处理排队任务
        //  STOP：不接受新任务，不处理排队任务，并中断正在进行的任务
        //  TIDYING：所有任务都已终止，调用terminate()方法
        //  TERMINATED：terminate()执行完毕后状态
        ThreadPoolExecutor threadPoolExecutor;


        // java 8
        // 实现Future、CompletionStage；完成时触发回调
        // complete*、cancel；触发；类似Stream，op入队，触发执行
        CompletableFuture completableFuture=null;
        CompletionStage completionStage;// 用于支持回调
        completableFuture.thenAccept(null);// complete时同步执行
        completableFuture.thenAcceptAsync(null);// complete时异步执行，默认ForkJoinPool.commonPool
        completableFuture.complete(null);
        {
            // 1，UNSAFE cas设置
            completableFuture.completeValue(null);
            // 2，触发回调
            completableFuture.postComplete();
        }


    }

    /**
     *
     */
    public static void threadPoolExecutor(){
        // 1，确保线程不结束。执行死循环；守护线程
        // 2，线程池内统一获取任务，执行。线程池任务队列
        // 3，线程不空转。未获取到任务，阻塞。
        ThreadPoolExecutor threadPoolExecutor=null;
        Executors executors;
        // 线程池工作线程，包含Thread；线程中断状态控制
        ThreadPoolExecutor.Worker worker;

        BlockingQueue<Runnable> workQueue;
        {

        }

        ThreadFactory threadFactory;// 线程工厂
        {
            Executors.DefaultThreadFactory defaultThreadFactory;// 普通工厂
            Executors.PrivilegedThreadFactory privilegedThreadFactory;// 优先级工厂
        }

        RejectedExecutionHandler handler;// 拒绝策略
        {
            ThreadPoolExecutor.AbortPolicy abortPolicy;// 抛异常。默。
            ThreadPoolExecutor.CallerRunsPolicy callerRunsPolicy;// 在调用者线程中运行任务
            ThreadPoolExecutor.DiscardOldestPolicy discardOldestPolicy;//丢弃最老，并尝试重新加入队列
            ThreadPoolExecutor.DiscardPolicy discardPolicy;//直接丢弃
        }

    }

}
